<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      class Dictionary {
        // 设置私有table
        table = {}

        // 设置tostring方法
        // 目的是 不管key值是什么类型的 都可以输出出来
        toStrFn(value){
          if(value === null){
            return 'NULL'
          }else if(value === undefined){
            return 'UNDEFINED'
          }else if(typeof value === 'string' || value instanceof String ){
            return value
          }
          // 如果上面的语句都不符合 那么就是复杂数据类型  返回JSON字符串
          return JSON.stringify(value)
        }

        hasKey(key){
          /* 
          undefined != null     // false    不判断类型  
          undefined !== null    // true     判断类型
          */
          return this.table[this.toStrFn(key)] != null
        }

        set(key ,value){
          if( key != null && value != null ){
            const tablekey = this.toStrFn(key)
            // 这里存值的方式 可以有优化的方式
            // 方式1. 缺点: 会丢失原始的key值  因为如果key是对象/数组 会被强制转换成json字符串
            // this.table[tablekey] = value 
            // 方式2. 单独封装类  这个的key值 只是作为标记  真正的key value 都存在了value里
            this.table[tablekey] = new realValue(key,value)
            return true
          }
          return false
        }

        get(key){
          // valueRes 此时就是realValue 类 返回出value就好  
          const valueRes = this.table[this.toStrFn(key)]
          return valueRes == null ? undefined : valueRes.value
        }

        remove(key){
          if(this.hasKey(key)){
            delete this.table[this.toStrFn(key)]
            return true
          }
          return false
        }


        keys(){
          return this.keyValues().map(item => item.key)
        }

        values(){
          return this.keyValues().map(item => item.value)
        }

        keyValues(){
          return Object.values(this.table)
        }

        forEach(cb){
          const keyValue = this.keyValues()
          for(let i =0 ; i<keyValue.length; i++){
            cb(keyValue[i].key , keyValue[i].value )
          }
        }
        
      }

      class realValue  {
        constructor(key , value){
          this.key = key
          this.value = value
        }
      }

      const mymap = new Dictionary()

      // 测试遍历方法
      // mymap.set({a:1} , 'a1')
      // mymap.set({b:1} , 'b1')
      // mymap.set({c:1} , 'c1')
      // mymap.forEach((key,value)=>{
      //   console.log(key,value);
      // })

    </script>
  </body>
</html>
